package com.site.utils;


import cn.hutool.core.bean.BeanUtil;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowKey;
import com.mybatisflex.core.util.StringUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.handle.Result;
import org.noear.solon.data.annotation.Cache;
import org.noear.solon.data.annotation.CachePut;
import org.noear.solon.data.annotation.CacheRemove;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Component
public class DbUtils {

    public List<Map<String, Object>> getAll(String table) {
        table = setTable(table);
        List<Row> rows = Db.selectAll(table);
        List<Map<String, Object>> mapList = new ArrayList<>();
        rows.forEach(item -> {
            Map<String, Object> result = item.toCamelKeysMap();
            mapList.add(result);
        });
        return mapList;
    }

    @Cache(key = "page:${table}:${page.num}", tags = "table:${table}")
    public Result<Page<Row>> page(String table, IPage page) {
        table = setTable(table);
        QueryWrapper query = QueryWrapper.create();
        if (page.getEq() != null) {
            query.where(page.getEq());
        }
        if (page.getLike() != null) {
            Set<String> entries = page.getLike().keySet();
            StringBuilder sql = new StringBuilder();
            for (String entry : entries) {
                sql.append(entry).append(" like '%").append(page.getLike().get(entry)).append("%' ");
            }
            query.where(sql.toString());
        }
        Page<Row> paginate = Db.paginate(table, page.getNum(), page.getSize(), query);
        return Result.succeed(paginate);
    }

    @Cache(key = "get:${table}:${id}", tags = "table:${table}")
    public Result<Row> get(String table, Serializable id) {
        table = setTable(table);
        Row result = Db.selectOneById(table, "id", id);
        return Result.succeed(result);
    }

    @CacheRemove(tags = "table:${table}")
    public Result<Object> add(String table, Row row) {
        table = setTable(table);
        RowKey rowKey = RowKey.of("id", KeyType.Auto, "auto", true);
        Row add = Row.ofKey(rowKey);
        BeanUtil.copyProperties(row, add);
        Set<String> entries = row.keySet();
        for (String entry : entries) {
            add.set(entry, row.get(entry));
        }
        int i = Db.insert(table, add);
        if (i == 0) {
            return Result.failure();
        } else {
            return Result.succeed(add);
        }
    }

    @CachePut(key = "get:${table}:${id}")
    @CacheRemove(tags = "table:${table}")
    public Result<String> put(String table, Row row) {
        table = setTable(table);
        RowKey rowKey = RowKey.of("id");
        Row put = Row.ofKey(rowKey);
        Set<String> entries = row.keySet();
        for (String entry : entries) {
            put.set(entry, row.get(entry));
        }
        int i = Db.updateById(table, put);
        return result(i);
    }

    private String setTable(String table) {
        table = StringUtil.camelToUnderline(table);
        return table;
    }

    private Result<String> result(int i) {
        if (i == 0) {
            return Result.failure();
        } else {
            return Result.succeed();
        }
    }

    @CacheRemove(tags = "table:${table}")
    public Result<String> delete(String table, Integer id) {
        table = setTable(table);
        RowKey rowKey = RowKey.of("id");
        Row delete = Row.ofKey(rowKey);
        delete.set("id", id);
        int i = Db.deleteById(table, delete);
        return result(i);
    }
}
